package com.brillilab.domain.vo.method;

import com.brillilab.domain.enums.method.ConvertMainSignType;
import com.brillilab.domain.enums.method.ConvertSignType;
import lombok.Data;
import org.elasticsearch.index.Index;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author wuzhiyu
 * @Title: ConvertDTO
 * @ProjectName processdata
 * @Description: TODO
 * @date 2019/4/169:36
 */
@Data
public class ConvertDTO {
    private List<String> mainSignList;
    private ConvertSignType signType;
    private ConvertMainSignType mainSignType;
    private List<IndexInfo> indexInfoList = new ArrayList<>();
    //private List<IndexInfo> allMatchSignIndexInfoList = new ArrayList<>();

    public ConvertDTO(ConvertMainSignType mainSignType, ConvertSignType signType) {
        this.mainSignType = mainSignType;
        Map<ConvertMainSignType, List<String>> signListMap = ConverConstantData.signListMap;
        this.mainSignList = signListMap.get(mainSignType);
        this.signType = signType;
    }

    public String getMainSign(Integer index) {
        if (signType == null) {
            return index.toString();
        }
        if (index > mainSignList.size() - 1) {
            throw new IndexOutOfBoundsException();
        }
        String str = mainSignList.get(index);
        return str;
    }

    public String getSignFormat() {
        switch (signType) {
            case DOT:
                return "%s.";
            case CN_DOT:
                return "%s、";
            case CN_BRACKET:
                return "（%s）";
            case BRACKET:
                return "(%s)";
            case HALF_BRACKET:
                return "%s)";
            case HALF_CN_BRACKET:
                return "%s）";
            case CN_ROUND:
                return "%s．";
            default:
                return "%s";
        }
    }

    public String getComboSign(Integer index) {
        String main = getMainSign(index);
        String comboSign = String.format(getSignFormat(), main);
        return comboSign;
    }

    public IndexInfo getIndexInfo(String textContext, Integer index) {
        IndexInfo info = new IndexInfo();
        info.setSignLength(getComboSign(index).length());
        String regexStr;
        switch (signType) {
            case DOT:
                if (mainSignType.equals(ConvertMainSignType.ALPA_LOW) || mainSignType.equals(ConvertMainSignType.ALPA_UP)) {
                    regexStr = "\\b" + getMainSign(index) + "{1}" + "\\.{1}";
                } else {
                    regexStr = "\\b" + getMainSign(index) + "\\.{1}\\s*";
                }
                break;
            case CN_DOT:
                /*
                [^\u4e00-\u9fa5]

                * */
                if (mainSignType.equals(ConvertMainSignType.CHINA)) {
                    regexStr = "\\b*" + getMainSign(index) + "、";
                } else {
                    regexStr = "\\b" + getMainSign(index) + "、";
                }
                break;
            case CN_ROUND:
                if (mainSignType.equals(ConvertMainSignType.CHINA)) {
                    regexStr = "\\b" + getMainSign(index) + "．";
                } else {
                    regexStr = "\\s*" + getMainSign(index) + "．";
                }
                break;
            case CN_BRACKET:
                regexStr = "（" + getMainSign(index) + "）";
                break;
            case BRACKET:
                regexStr = "\\(" + getMainSign(index) + "\\)";
                break;
            case HALF_BRACKET:
                regexStr = "(?<![\\(〜~:：])\\b" + getMainSign(index) + "\\)";
                break;
            case HALF_CN_BRACKET:
                regexStr = "(?<![（〜~:：])\\b" + getMainSign(index) + "）";
                break;
            default:
                regexStr = "\\b" + getMainSign(index) + "\\b";
                break;
        }
        Integer pos = getRegexMatchIndex(textContext, regexStr, index - 1);
        if (pos > -1) {
            if (indexInfoList.size() > 0) {
                String sign = getComboSign(index - 1);
                Optional<IndexInfo> opt = indexInfoList.stream().filter(i -> i.getSign().equals(sign)).findFirst();
                if (opt.isPresent()) {
                    if (opt.get().getIndex() < pos) {
                        info.setIndex(pos);
                        info.setSign(getComboSign(index));
                        indexInfoList.add(info);
                    }
                }
            } else {
                info.setIndex(pos);
                info.setSign(getComboSign(index));
                indexInfoList.add(info);
            }
        }
        return info;
    }


    public void regetIndexInfo(String textContext) {
        this.indexInfoList.clear();
        for (int i = 0; i < mainSignList.size(); i++) {
            getIndexInfo(textContext, i);
        }
    }

    private Integer getRegexMatchIndex(String content, String regexStr,Integer preIndex) {
        Pattern p = Pattern.compile(regexStr);
        Matcher m = p.matcher(content);
        if(indexInfoList.size() > 0){
            String sign = getComboSign(preIndex);
            Optional<IndexInfo> opt = indexInfoList.stream().filter(i -> i.getSign().equals(sign)).findFirst();
            while (opt.isPresent()&&m.find()){
                if(m.start()>opt.get().getIndex()){
                    return m.start();
                }
            }
        }else{
            if (m.find()) {
                return m.start();
            }
        }
        return -1;
    }
}
